﻿using System;
using System.IO;
using System.Data;
using System.Collections.Generic;
using Excel;
using UnityEngine;
using System.Collections;
using HoneyFramework;
public class TerrainItemData{
	public string id = string.Empty;
	public TerrainDefinition def; 
	public int index = 0;
	public float orderPosition = 0;
	public float rotationAngle = 0;
}
class Block{
	public const int BLOCK_SIZE = 10;
	// 起始点坐标
	public List<Vector2i> startPoints = new List<Vector2i>();
	// 地形数据
	public string[,] terrainValue = new string[BLOCK_SIZE,BLOCK_SIZE];
	public string GetTerrainType(int x,int y){
		x = x % BLOCK_SIZE;
		if (x < 0) {
			x += BLOCK_SIZE;
		}
		y = y % BLOCK_SIZE;
		if (y < 0) {
			y += BLOCK_SIZE;
		}
		return terrainValue [x, y];
	}
	public bool Contains(int x,int y){
		foreach(Vector2i point in startPoints){
			if (point.x <= x && point.y <= y &&(point.x+BLOCK_SIZE) > x && (point.y+BLOCK_SIZE)> y) {
				return true;
			}
		}
		return false;
	}
	public bool Equals(Block bk){
		for (int x = 0; x < BLOCK_SIZE; x++) {
			for (int y = 0; y < BLOCK_SIZE; y++) {
				if (!terrainValue [x, y].Equals (bk.terrainValue [x, y])) {
					return false;
				}
			}
		}
		return true;
	}
}
public class ExcelTerrainManager
{
	private static List<Block> blocks;
	public static int ColumnsCount;
	public static int RowsCount;
	private static List<TerrainItemData> definitions = new List<TerrainItemData>();
	static public void LoadDefinitions(){
		string path = Application.streamingAssetsPath;
		FileStream stream = File.Open (path + "/mapData.xlsx", FileMode.Open, FileAccess.Read);
		IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader (stream);
		DataSet result = excelReader.AsDataSet ();
		DataTable terrain = result.Tables[0];
		ColumnsCount = terrain.Columns.Count;
		if (ColumnsCount > 1500) {
			ColumnsCount = 1500;
		}
		RowsCount = terrain.Rows.Count;
		if (RowsCount > 1500) {
			RowsCount = 1500;
		}
		blocks =FilterSameChunk( terrain.Rows);
		Debug.Log (string.Format("blocks Count = {0}",blocks.Count));
		terrain = result.Tables[1];

		for(int i = 1;i<terrain.Rows.Count;i++){
			TerrainItemData td = new TerrainItemData ();
			string tname = terrain.Rows [i] [1].ToString ().Trim();
			td.id = terrain.Rows [i] [0].ToString().Trim();
			td.orderPosition = float.Parse (terrain.Rows [i] [3].ToString ())/100;
			if (td.orderPosition > 1) {
				td.orderPosition = 1;
			}
			td.rotationAngle = float.Parse (terrain.Rows [i] [2].ToString ());
			td.def = TerrainDefinition.definitions.Find (o => o.name.Equals(tname));
			if (td.def != null) {
				definitions.Add (td);
			}

		}
	}
	static private List<Block> FilterSameChunk(DataRowCollection Rows){
		List<Block> blocks = new List<Block> ();
		bool finded = false;
		Block block = new Block();
		for (int x = 0; x < ColumnsCount-1; x+=Block.BLOCK_SIZE) {
			for (int y = 0; y < RowsCount-1; y+=Block.BLOCK_SIZE) {
				for (int px = 0; px < Block.BLOCK_SIZE; px++) {
					for (int py = 0; py < Block.BLOCK_SIZE; py++) {
						block.terrainValue [px,py] = Rows [x + px] [y + py].ToString ().Trim ();
					}
				}
				finded = false;
				for (int i = blocks.Count - 1; i >= 0; i--) {
					if (block.Equals (blocks [i])) {
						blocks [i].startPoints.Add (new Vector2i (x, y));
						finded = true;
						break;
					}
				}
				if (!finded) {
					block.startPoints.Add (new Vector2i (x, y));
					blocks.Add (block);
					block = new Block ();
				}
			}
		}
		return blocks;
	}
	static private string GetTerType(int x,int y){
		Block block;
		for (int i = blocks.Count - 1; i >= 0; i--) {
			block = blocks [i];
			if (block.Contains (x,y)) {
				return block.GetTerrainType (x,y);
			}
		}
		return "";
	}
	static public TerrainItemData GetTerrain(int x,int y){

		while (x < 0) {
			x += ColumnsCount;
		}
		while (x >= ColumnsCount) {
			x -= ColumnsCount;
		}

		while (y < 0) {
			y += RowsCount;
		}
		while (y >= RowsCount) {
			y -= RowsCount;
		}
		string index = GetTerType(x,y);
		if (index.Equals ("")) {
			index="7";
		}
		return definitions.Find (o => o.id.Equals(index));
	}
}



